/** Helper functions for writing migration tests */
#pragma once

#include <cstdio>
#include <fcntl.h>
#include <malloc.h>
#include <unistd.h>

#include <jni.h>

#include <utils/serializer.h>

#ifdef __cplusplus
extern "C" {
#endif

bool bsg_report_header_write(bsg_report_header *header, int fd);

#ifdef __cplusplus
}
#endif

static void write_str_to_file(char *contents, const char *path) {
  int fd = open(path, O_WRONLY | O_CREAT, 0644);
  if (fd == -1) {
    return;
  }

  write(fd, contents, strlen(contents));
}

/**
 * Write an event to disk
 */
static bool write_struct_to_file(void *event, int version, size_t expected_length,
                          const char *path) {
  int fd = open(path, O_WRONLY | O_CREAT, 0644);
  if (fd == -1) {
    return false;
  }

  bsg_report_header header = {version, 0, {0}};
  if (!bsg_report_header_write(&header, fd)) {
    return false;
  }

  ssize_t actual_length = write(fd, event, expected_length);
  close(fd);

  return actual_length == expected_length;
}

static void insert_crumb(bugsnag_breadcrumb *array, int index, const char *name,
                  bugsnag_breadcrumb_type type, long long timestamp,
                  const char *meta_str) {
  auto crumb = bugsnag_breadcrumb{.type = type};
  strcpy(crumb.name, name);
  sprintf(crumb.timestamp, "t%llu", timestamp);
  bsg_add_metadata_value_str(&crumb.metadata, "metadata", "message", meta_str);

  memcpy(&(array[index]), &crumb, sizeof(bugsnag_breadcrumb));
}

/**
 * Writes a JSON file based on a struct generated by a function
 *
 * @param env              JNI Environment for parsing temp file path
 * @param event_generator  A function returning an allocated event struct
 * @param version          The version of the event struct from generator
 * @param event_length     Length of the allocated event struct in bytes
 * @param temp_file        File path for writing JSON output
 */
static void write_json_for_event(JNIEnv *env, void *(event_generator)(), int version,
                          int event_length, jstring temp_file) {
  const char *path = (*env).GetStringUTFChars(temp_file, nullptr);

  // (old format) event struct -> file on disk
  void *old_event = event_generator();
  bool success = write_struct_to_file(old_event, version, event_length, path);
  free(old_event);

  // file on disk -> latest event type
  bugsnag_event *parsed_event = bsg_deserialize_event_from_file((char *)path);
  char *output = bsg_serialize_event_to_json_string(parsed_event);
  free(parsed_event);

  // latest event type -> temp file
  write_str_to_file(output, path);
  free(output);
}
